/******************************************************************************

  File Name     : nnie_basicalg.h
  Version       : Initial Draft
  Author        : tongzhilin
  Created       : 2020/8/7
  Last Modified :
  Description   : nnie_basicalg
  Function List :
  History       :
  1.Date        : 2020/8/7
    Author      : tongzhilin
    Modification: Created file

******************************************************************************/
#pragma once
#include "mp_common.h"
#include "hinnie_session.h"
#include "alg_struct.h"

#define l_eye_rel_x     0.3333333333333333      //236/600
#define l_eye_rel_y     0.45                    //270/600
#define r_eye_rel_x     0.6666666666666667      //364/600
#define r_eye_rel_y     0.45                    //270/600
#define m_rel_x         0.5                     //300/600
#define m_rel_y         0.83333333333333333     //404/60

#define l_eye_point_x     34.44654466
#define l_eye_point_y     44.88
#define r_eye_point_x     74.51347193
#define r_eye_point_y     44.88
#define nose_point_x      53.74434328
#define nose_point_y      68.67863066
#define l_mouse_point_x   39.61127824
#define l_mouse_point_y   88.35199512
#define r_mouse_point_x   70.26382275
#define r_mouse_point_y   88.56349917

#define MAX_MODEL_NUM 128

typedef enum
{
    IMG_PRE_TYPE_IMAGE          = 0x0,
    IMG_PRE_TYPE_IMAGES         = 0x1,
    IMG_PRE_TYPE_IMAGE_RECTS    = 0x2,
    IMG_PRE_TYPE_IMAGE_LMK5PTS  = 0x3,
    IMG_PRE_TYPE_IMAGE_LMK3PTS  = 0x4,

    IMG_PRE_TYPE_BUTT           = 0xFF
}IMG_PRE_TYPE_E;

class ModelList
{
public:
    ModelList()
    {
        m_spModel = nullptr;
        memset(m_cName, 0, ALG_MODEL_NAME_SIZE);
    }
    virtual ~ModelList()
    {
        m_spModel = nullptr;
    }
    std::shared_ptr<HinnieModel>    m_spModel;
    char                            m_cName[ALG_MODEL_NAME_SIZE];
};

class NnieAlgBasic
{
public:
    NnieAlgBasic(const char* _pModelName, INT32 _s32MaxBatch = 16);
    virtual ~NnieAlgBasic();
public:
    /*
    ** alg funcs
    */
    INT32 alg_init(ALG_INIT_PARAMS* _pstParam);
    INT32 alg_deinit();
    INT32 alg_get_input_c();
    INT32 alg_get_input_h();
    INT32 alg_get_input_w();
    INT32 alg_get_output_blob_n();
    INT32 alg_get_output_c(INT32 _s32BlobN);
    INT32 alg_get_output_h(INT32 _s32BlobN);
    INT32 alg_get_output_w(INT32 _s32BlobN);
    INT32 alg_set_nnie_id();

    INT32 alg_flash_output_blob();

    static float alg_feature_compare_consin(ALG_FACEFEATURE_RESULT_S* _pstFeat1, ALG_FACEFEATURE_RESULT_S* _pstFeat2);
    static float alg_feature_compare_euclidean(ALG_FACEFEATURE_RESULT_S* _pstFeat1, ALG_FACEFEATURE_RESULT_S* _pstFeat2);
public:
    /*
    ** alg funcs: virtual func
    */
    //run the input image
    virtual INT32 alg_run_image(ALG_IMAGE_S* _pstImage, INT32 _s32MaxRet, void *_pstResult);
    //run the input images batch
    //virtual INT32 alg_run_images();
    //run the little images in input image,get little images by all rects on the input image, run batch
    virtual INT32 alg_run_image_rects(ALG_IMAGE_S* _pstImage, ALG_RECT_S *_pstRect, INT32 _s32RectNum, void *_pstResult);
    //run the little images in input image,get little images by all lmk5pts on the input image, run batch
    virtual INT32 alg_run_image_lmk5pts(ALG_IMAGE_S* _pstImage, ALG_FACELMK_RESULT_S *_pstLmk, INT32 _s32FaceNum, void *_pstResult);
    virtual INT32 alg_run_image_lmk3pts(ALG_IMAGE_S* _pstImage, ALG_FACELMK_RESULT_S *_pstLmk, INT32 _s32FaceNum, void *_pstResult);

protected:
    void ab_image_pre(IMG_PRE_TYPE_E _ePreType, ALG_IMAGE_S *_pstAlgImage);
    void ab_image_proc();
    virtual bool ab_image_post();

protected:
    void set_rects(std::vector<ALG_RECT_S>& _stvRects, INT32 width, INT32 height);
    void set_facepoints(std::vector<ALG_FACE_POINTS_S>& points);

protected:
    static std::vector<ModelList>   m_stvModelInfo;
    /*
    ** construct init
    */
    std::shared_ptr<HinnieModel>    m_spNnModel;
    char                            m_cModelName[ALG_MODEL_NAME_SIZE];
    std::unique_ptr<HinnieSession>  m_spNNSession;
    // input blob
    std::vector<SVP_BLOB_S>         m_stvInputSvpBlob;
    // output blob
    std::vector<SVP_BLOB_S>         m_stvOutputSvpBlob;
    std::vector<int32_t*>           m_s32vOutBlob_Viraddr;
    std::vector<INT32>              m_s32vOutBlob_W;
    std::vector<INT32>              m_s32vOutBlob_S;
    std::vector<INT32>              m_s32vOutBlob_H;
    std::vector<INT32>              m_s32vOutBlob_C;
    INT32                           m_max_batch = 16;
    INT32                           m_cur_batch;
    INT32                           m_begin;


    INT32                           m_input_batch;
    /*
    ** init
    */
    float                           m_threshold;    //有些模型没有阈值
    HINN_SESSION_NNIE_ID_E          m_nnid;
    INT32                           m_enable;       //enable暂时没有使用

    /*
    ** rects after pre
    */
    std::vector<ALG_RECT_S>         m_rects;

    /*
    ** affine/refine src and ref points
    */
    std::vector<ALG_FACE_POINTS_S>  m_points_src;
    ALG_FACE_POINTS_S               m_point_ref1;
    ALG_FACE_POINTS_S               m_point_ref2;
};

